





<!DOCTYPE html>
<html class="writer-html5" lang="zh-CN" >
<head>
  <meta charset="utf-8">
  
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
  <title>Relay 介绍 &mdash; tvm 0.8.dev1982 文档</title>
  

  
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
  <link rel="stylesheet" href="../_static/css/theme.css" type="text/css" />
  <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
  <link rel="stylesheet" href="../_static/css/theme.css" type="text/css" />
  <link rel="stylesheet" href="../_static/gallery.css" type="text/css" />
  <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
  <link rel="stylesheet" href="../_static/css/tlcpack_theme.css" type="text/css" />

  
  
    <link rel="shortcut icon" href="../_static/tvm-logo-square.png"/>
  

  
  
  
  
    
      <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
        <script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
        <script src="../_static/jquery.js"></script>
        <script src="../_static/underscore.js"></script>
        <script src="../_static/doctools.js"></script>
        <script src="../_static/translations.js"></script>
    
    <script type="text/javascript" src="../_static/js/theme.js"></script>

    
    <script type="text/javascript" src="../_static/js/tlcpack_theme.js"></script>
    <link rel="index" title="索引" href="../genindex.html" />
    <link rel="search" title="搜索" href="../search.html" />
    <link rel="next" title="Relay Operator Strategy" href="relay_op_strategy.html" />
    <link rel="prev" title="混合前端开发指南" href="hybrid_script.html" /> 
</head>

<body class="wy-body-for-nav">

   
  <div class="wy-grid-for-nav">
    
    
<header class="header">
    <div class="innercontainer">
      <div class="headerInner d-flex justify-content-between align-items-center">
          <div class="headerLogo">
               <a href="https://tvm.apache.org/"><img src=https://tvm.apache.org/assets/images/logo.svg alt="logo"></a>
          </div>

          <div id="headMenu" class="headerNav">
            <button type="button" id="closeHeadMenu" class="navCloseBtn"><img src="../_static/img/close-icon.svg" alt="Close"></button>
             <ul class="nav">
                <li class="nav-item">
                   <a class="nav-link" href=https://tvm.apache.org/community>Community</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvm.apache.org/download>Download</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvm.apache.org/vta>VTA</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvm.apache.org/blog>Blog</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvm.apache.org/docs>Docs</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvmconf.org>Conference</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://github.com/apache/tvm/>Github</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvmchinese.github.io/declaration_zh_CN.html>About-Translators</a>
                </li>
             </ul>
               <div class="responsivetlcdropdown">
                 <button type="button" class="btn-link">
                   ASF
                 </button>
                 <ul>
                     <li>
                       <a href=https://apache.org/>Apache Homepage</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/licenses/>License</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/foundation/sponsorship.html>Sponsorship</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/security/>Security</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/foundation/thanks.html>Thanks</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/events/current-event>Events</a>
                     </li>
                     <li>
                       <a href=https://www.zhihu.com/column/c_1429578595417563136>Zhihu</a>
                     </li>
                 </ul>
               </div>
          </div>
            <div class="responsiveMenuIcon">
              <button type="button" id="menuBtn" class="btn-menu"><img src="../_static/img/menu-icon.svg" alt="Menu Icon"></button>
            </div>

            <div class="tlcDropdown">
              <div class="dropdown">
                <button type="button" class="btn-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                  ASF
                </button>
                <div class="dropdown-menu dropdown-menu-right">
                  <ul>
                     <li>
                       <a href=https://apache.org/>Apache Homepage</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/licenses/>License</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/foundation/sponsorship.html>Sponsorship</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/security/>Security</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/foundation/thanks.html>Thanks</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/events/current-event>Events</a>
                     </li>
                     <li>
                       <a href=https://www.zhihu.com/column/c_1429578595417563136>Zhihu</a>
                     </li>
                  </ul>
                </div>
              </div>
          </div>
       </div>
    </div>
 </header>
 
    <nav data-toggle="wy-nav-shift" class="wy-nav-side fixed">
      <div class="wy-side-scroll">
        <div class="wy-side-nav-search" >
          

          
            <a href="../index.html">
          

          
            
            <img src="../_static/tvm-logo-small.png" class="logo" alt="Logo"/>
          
          </a>

          
            
            
                <div class="version">
                  0.8.dev1982
                </div>
            
          

          
<div role="search">
  <form id="rtd-search-form" class="wy-form" action="../search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" />
    <input type="hidden" name="check_keywords" value="yes" />
    <input type="hidden" name="area" value="default" />
  </form>
</div>

          
        </div>

        
        <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
          
            
            
              
            
            
              <p class="caption" role="heading"><span class="caption-text">如何开始</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../install/index.html">安装 TVM</a></li>
<li class="toctree-l1"><a class="reference internal" href="../contribute/index.html">贡献者指南</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">用户引导</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../tutorial/index.html">User Tutorial</a></li>
<li class="toctree-l1"><a class="reference internal" href="../how_to/index.html">How To Guides</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">开发者引导</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../dev/tutorial/index.html">Developer Tutorial</a></li>
<li class="toctree-l1"><a class="reference internal" href="../dev/how_to/how_to.html">开发者指南</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">架构指南</span></p>
<ul class="current">
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Design and Architecture</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="index.html#example-compilation-flow">编译流程示例</a></li>
<li class="toctree-l2"><a class="reference internal" href="index.html#logical-architecture-components">逻辑架构组件</a></li>
<li class="toctree-l2"><a class="reference internal" href="index.html#tvm-support">tvm/support</a></li>
<li class="toctree-l2"><a class="reference internal" href="index.html#tvm-runtime">tvm/runtime</a></li>
<li class="toctree-l2"><a class="reference internal" href="index.html#tvm-node">tvm/node</a></li>
<li class="toctree-l2"><a class="reference internal" href="index.html#tvm-ir">tvm/ir</a></li>
<li class="toctree-l2"><a class="reference internal" href="index.html#tvm-target">tvm/target</a></li>
<li class="toctree-l2"><a class="reference internal" href="index.html#tvm-tir">tvm/tir</a></li>
<li class="toctree-l2"><a class="reference internal" href="index.html#tvm-arith">tvm/arith</a></li>
<li class="toctree-l2"><a class="reference internal" href="index.html#tvm-te">tvm/te</a></li>
<li class="toctree-l2"><a class="reference internal" href="index.html#tvm-topi">tvm/topi</a></li>
<li class="toctree-l2 current"><a class="reference internal" href="index.html#tvm-relay">tvm/relay</a><ul class="current">
<li class="toctree-l3 current"><a class="current reference internal" href="#">Relay 介绍</a><ul>
<li class="toctree-l4"><a class="reference internal" href="#build-a-computational-graph-with-relay">使用Relay建立一个计算图</a></li>
<li class="toctree-l4"><a class="reference internal" href="#module-support-multiple-functions-graphs">Module: Support Multiple Functions (Graphs)</a></li>
<li class="toctree-l4"><a class="reference internal" href="#let-binding-and-scopes">Let Binding and Scopes</a></li>
<li class="toctree-l4"><a class="reference internal" href="#why-we-might-need-let-binding">Why We Might Need Let Binding</a></li>
<li class="toctree-l4"><a class="reference internal" href="#implication-on-ir-transformations">Implication on IR Transformations</a></li>
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="relay_op_strategy.html">Relay Operator Strategy</a></li>
<li class="toctree-l3"><a class="reference internal" href="convert_layout.html">Convert Layout Pass</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="index.html#tvm-autotvm">tvm/autotvm</a></li>
<li class="toctree-l2"><a class="reference internal" href="index.html#frontends">Frontends</a></li>
<li class="toctree-l2"><a class="reference internal" href="index.html#security">安全</a></li>
<li class="toctree-l2"><a class="reference internal" href="index.html#microtvm">microTVM</a></li>
</ul>
</li>
</ul>
<p class="caption" role="heading"><span class="caption-text">主题引导</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../topic/microtvm/index.html">microTVM：裸机使用TVM</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topic/vta/index.html">VTA: Versatile Tensor Accelerator</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">参考指南</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../reference/langref/index.html">语言参考</a></li>
<li class="toctree-l1"><a class="reference internal" href="../reference/api/python/index.html">Python API</a></li>
<li class="toctree-l1"><a class="reference internal" href="../reference/api/links.html">Other APIs</a></li>
<li class="toctree-l1"><a class="reference internal" href="../reference/publications.html">Publications</a></li>
<li class="toctree-l1"><a class="reference internal" href="../genindex.html">索引</a></li>
</ul>

            
          
        </div>
        
      </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
      
      <nav class="wy-nav-top" aria-label="top navigation" data-toggle="wy-nav-top">
        
            <div class="togglemenu">

            </div>
            <div class="nav-content">
              <!-- tvm -->
              Table of content
            </div>
        
      </nav>


      <div class="wy-nav-content">
        
        <div class="rst-content">
        

          




















<div role="navigation" aria-label="breadcrumbs navigation">

  <ul class="wy-breadcrumbs">
    
      <li><a href="../index.html">Docs</a> <span class="br-arrow">></span></li>
        
          <li><a href="index.html">Design and Architecture</a> <span class="br-arrow">></span></li>
        
      <li>Relay 介绍</li>
    
    
      <li class="wy-breadcrumbs-aside">
        
            
            <a href="../_sources/arch/relay_intro.rst.txt" rel="nofollow"> <img src="../_static//img/source.svg" alt="viewsource"/></a>
          
        
      </li>
    
  </ul>

  
  <hr/>
</div>
          <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
           <div itemprop="articleBody">
            
  <div class="section" id="introduction-to-relay-ir">
<span id="relay-dev-intro"></span><h1>Relay 介绍<a class="headerlink" href="#introduction-to-relay-ir" title="永久链接至标题">¶</a></h1>
<p>本文将介绍 NNVM 的下一代中间表示: Relay。 我们期待两种背景的读者——具有编程语言背景的读者和熟悉计算图表示的深度学习框架开发人员。</p>
<p>我们在这里简要总结Relay的设计目标，并将在后面部分讨论这些要点。</p>
<ul class="simple">
<li><p>支持传统的数据流风格的编程和变换。</p></li>
<li><p>支持函数式编程风格，包括函数式编程里的scoping 和 let-binding，并且我们将Relay设计成了一门可微分的语言。</p></li>
<li><p>支持数据流风格和函数式风格的混合编程。</p></li>
</ul>
<div class="section" id="build-a-computational-graph-with-relay">
<h2>使用Relay建立一个计算图<a class="headerlink" href="#build-a-computational-graph-with-relay" title="永久链接至标题">¶</a></h2>
<p>传统的深度学习框架使用计算图作为它们的中间表示。 计算图（或数据流图）是代表计算过程的有向无环图（DAG）。 尽管由于缺少控制流，数据流图在计算能力方面受到限制，但它们的简单性使其易于实现自动微分并针对异构执行环境进行编译（例如，在专用硬件上执行计算图的一部分，即子图）。</p>
<img alt="https://raw.githubusercontent.com/tvmai/tvmai.github.io/main/images/relay/dataflow.png" class="align-center" src="https://raw.githubusercontent.com/tvmai/tvmai.github.io/main/images/relay/dataflow.png" />
<p>我们可以使用 Relay 构建计算（数据流）图。具体来说，上面的代码展示了如何构造一个简单只有两个节点的计算图。你会发现示例的语法与第一代 NNVM 等现有基于计算图的中间表示没有太大区别，唯一的区别只是术语的不同：</p>
<ul class="simple">
<li><p>现有框架通常使用图和子图</p></li>
<li><p>Relay 使用函数，例如 <code class="docutils literal notranslate"><span class="pre">fn</span> <span class="pre">(%x)</span></code> 来表示图</p></li>
</ul>
<p>每个数据流节点都是 Relay 中的一个 CallNode。 Relay Python DSL 允许用户快速地构建数据流图。在上面的代码中需要注意的是我们显式地构造了一个 Add 节点，其中两个输入点都指向 <code class="docutils literal notranslate"><span class="pre">%1</span></code>。当深度学习框架对上面这段程序进行推理时，它将会按照拓扑顺序进行计算，并且 <code class="docutils literal notranslate"><span class="pre">%1</span></code> 只会被计算一次。尽管这对于深度学习框架构建者来说是很自然的，但它可能会让 PL（程序语言）的研究者感到惊讶。如果我们实现一个简单的visitor来打印结果并将结果视为嵌套的 Call 表达式，它就变成了 <code class="docutils literal notranslate"><span class="pre">log(%x)</span> <span class="pre">+</span> <span class="pre">log(%x)</span></code> 。</p>
<p>这种歧义是由于当 DAG 中存在共享节点时对程序语义的不同理解造成的。在正常的函数式 IR 中，嵌套表达式被视为表达式树，而没有考虑 <code class="docutils literal notranslate"><span class="pre">%1</span></code> 在 <code class="docutils literal notranslate"><span class="pre">%2</span></code> 中其实被重用两次。</p>
<p>Relay IR 注意到了这个区别。深度学习框架用户经常使用这种方式构建计算图的时候经常会发生 DAG 节点的重用。因此，当我们以文本格式打印 Relay 程序时，我们每行打印一个 CallNode ，并且给每个 CallNode 分配一个临时 id <code class="docutils literal notranslate"><span class="pre">(%1,</span> <span class="pre">%2)</span></code>，以便可以在程序的后续部分中引用每个被重用的节点。</p>
</div>
<div class="section" id="module-support-multiple-functions-graphs">
<h2>Module: Support Multiple Functions (Graphs)<a class="headerlink" href="#module-support-multiple-functions-graphs" title="永久链接至标题">¶</a></h2>
<p>到此为止我们已经介绍了如何将一个数据流图构建为一个函数。我们可以很自然的想到：我们是否可以支持多个函数并使得它们可以相互调用？Relay 支持将多个函数打包在一个模块中；下面的代码展示了函数调用另一个函数的例子：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>def @muladd(%x, %y, %z) {
  %1 = mul(%x, %y)
  %2 = add(%1, %z)
  %2
}
def @myfunc(%x) {
  %1 = @muladd(%x, 1, 2)
  %2 = @muladd(%1, 2, 3)
  %2
}
</pre></div>
</div>
<p>The Module can be viewed as a <code class="docutils literal notranslate"><span class="pre">Map&lt;GlobalVar,</span> <span class="pre">Function&gt;</span></code>. Here GlobalVar is just an id that is used to represent the functions
in the module. <code class="docutils literal notranslate"><span class="pre">&#64;muladd</span></code> and <code class="docutils literal notranslate"><span class="pre">&#64;myfunc</span></code> are GlobalVars in the above example. When a CallNode is used to call another function,
the corresponding GlobalVar is stored in the op field of the CallNode. It contains a level of indirection – we need to look up
body of the called function from the module using the corresponding GlobalVar. In this particular case, we could also directly
store the reference to the Function as op in the CallNode. So, why do we need to introduce GlobalVar? The main reason is that
GlobalVar decouples the definition/declaration and enables recursion and delayed declaration of the function.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>def @myfunc(%x) {
  %1 = equal(%x, 1)
   if (%1) {
      %x
   } else {
     %2 = sub(%x, 1)
     %3 = @myfunc(%2)
      %4 = add(%3, %3)
      %4
  }
}
</pre></div>
</div>
<p>在上面的例子中， <code class="docutils literal notranslate"><span class="pre">&#64;myfunc</span></code> 递归调用它自身。使用全局变量 <code class="docutils literal notranslate"><span class="pre">&#64;myfunc</span></code> 来避免在数据结构中的循环依赖。到这里，我们已经介绍了 Relay 的基本概念。值得注意的是， Relay 相较于 NNVM 有如下改进：</p>
<ul class="simple">
<li><p>Succinct text format that eases debugging of writing passes.</p></li>
<li><p>First-class support for subgraphs-functions, in a joint module, this enables further chance of joint optimizations such as inlining and calling convention specification.</p></li>
<li><p>Naive front-end language interop, for example, all the data structure can be visited in Python, which allows quick prototyping of optimizations in Python and mixing them with C++ code.</p></li>
</ul>
</div>
<div class="section" id="let-binding-and-scopes">
<h2>Let Binding and Scopes<a class="headerlink" href="#let-binding-and-scopes" title="永久链接至标题">¶</a></h2>
<p>So far, we have introduced how to build a computational graph in the good old way used in deep learning frameworks.
This section will talk about a new important construct introduced by Relay – let bindings.</p>
<p>Let binding is used in every high-level programming language. In Relay, it is a data structure with three
fields <code class="docutils literal notranslate"><span class="pre">Let(var,</span> <span class="pre">value,</span> <span class="pre">body)</span></code>. When we evaluate a let expression, we first evaluate the value part, assign
it to the var, then return the evaluated result in the body expression.</p>
<p>You can use a sequence of let bindings to construct a logically equivalent program to a dataflow program.
The code example below shows one program with two forms side by side.</p>
<img alt="https://raw.githubusercontent.com/tvmai/tvmai.github.io/main/images/relay/dataflow_vs_func.png" class="align-center" src="https://raw.githubusercontent.com/tvmai/tvmai.github.io/main/images/relay/dataflow_vs_func.png" />
<p>The nested let binding is called A-normal form, and it is commonly used as IRs in functional programming languages.
Now, please take a close look at the AST structure. While the two programs are semantically identical
(so are their textual representations, except that A-normal form has let prefix), their AST structures are different.</p>
<p>Since program optimizations take these AST data structures and transform them, the two different structures will
affect the compiler code we are going to write. For example, if we want to detect a pattern <code class="docutils literal notranslate"><span class="pre">add(log(x),</span> <span class="pre">y)</span></code>:</p>
<ul class="simple">
<li><p>In the data-flow form, we can first access the add node, then directly look at its first argument to see if it is a log</p></li>
<li><p>In the A-normal form, we cannot directly do the check anymore, because the first input to add is <code class="docutils literal notranslate"><span class="pre">%v1</span></code> – we will need to keep a map from variable to its bound values and look up that map, in order to know that <code class="docutils literal notranslate"><span class="pre">%v1</span></code> is a log.</p></li>
</ul>
<p>Different data structures will impact how you might write transformations, and we need to keep that in mind.
So now, as a deep learning framework developer, you might ask, Why do we need let bindings?
Your PL friends will always tell you that let is important – as PL is a quite established field,
there must be some wisdom behind that.</p>
</div>
<div class="section" id="why-we-might-need-let-binding">
<h2>Why We Might Need Let Binding<a class="headerlink" href="#why-we-might-need-let-binding" title="永久链接至标题">¶</a></h2>
<p>One key usage of let binding is that it specifies the scope of computation. Let us take a look at the following example,
which does not use let bindings.</p>
<img alt="https://raw.githubusercontent.com/tvmai/tvmai.github.io/main/images/relay/let_scope.png" class="align-center" src="https://raw.githubusercontent.com/tvmai/tvmai.github.io/main/images/relay/let_scope.png" />
<p>The problem comes when we try to decide where we should evaluate node <code class="docutils literal notranslate"><span class="pre">%1</span></code>. In particular, while the text format seems
to suggest that we should evaluate node <code class="docutils literal notranslate"><span class="pre">%1</span></code> outside the if scope, the AST(as shown in the picture) does not suggest so.
Actually, a dataflow graph never defines its scope of the evaluation. This introduces some ambiguity in the semantics.</p>
<p>This ambiguity becomes more interesting when we have closures. Consider the following program, which returns a closure.
We don’t know where should we compute <code class="docutils literal notranslate"><span class="pre">%1</span></code>; it can be either inside or outside the closure.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">fn</span> <span class="p">(</span><span class="o">%</span><span class="n">x</span><span class="p">)</span> <span class="p">{</span>
  <span class="o">%</span><span class="mi">1</span> <span class="o">=</span> <span class="n">log</span><span class="p">(</span><span class="o">%</span><span class="n">x</span><span class="p">)</span>
  <span class="o">%</span><span class="mi">2</span> <span class="o">=</span> <span class="n">fn</span><span class="p">(</span><span class="o">%</span><span class="n">y</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">add</span><span class="p">(</span><span class="o">%</span><span class="n">y</span><span class="p">,</span> <span class="o">%</span><span class="mi">1</span><span class="p">)</span>
  <span class="p">}</span>
  <span class="o">%</span><span class="mi">2</span>
<span class="p">}</span>
</pre></div>
</div>
<p>A let binding solves this problem, as the computation of the value happens at the let node. In both programs,
if we change <code class="docutils literal notranslate"><span class="pre">%1</span> <span class="pre">=</span> <span class="pre">log(%x)</span></code> to <code class="docutils literal notranslate"><span class="pre">let</span> <span class="pre">%v1</span> <span class="pre">=</span> <span class="pre">log(%x)</span></code>, we clearly specify the computation location to
be outside of the if scope and closure. As you can see let-binding gives a more precise specification of the computation site
and could be useful when we generate backend code (as such specification is in the IR).</p>
<p>On the other hand, the dataflow form, which does not specify the scope of computation, does have its own advantages
– namely, we don’t need to worry about where to put the let when we generate the code. The dataflow form also gives more freedom
to the later passes to decide where to put the evaluation point. As a result, it might not be a bad idea to use data flow
form of the program in the initial phases of optimizations when you find it is convenient.
Many optimizations in Relay today are written to optimize dataflow programs.</p>
<p>However, when we lower the IR to an actual runtime program, we need to be precise about the scope of computation.
In particular, we want to explicitly specify where the scope of computation should happen when we are using
sub-functions and closures. Let-binding can be used to solve this problem in later stage execution specific optimizations.</p>
</div>
<div class="section" id="implication-on-ir-transformations">
<h2>Implication on IR Transformations<a class="headerlink" href="#implication-on-ir-transformations" title="永久链接至标题">¶</a></h2>
<p>Hopefully, by now you are familiar with the two kinds of representations.
Most functional programming languages do their analysis in A-normal form,
where the analyzer does not need to be mindful that the expressions are DAGs.</p>
<p>Relay choose to support both the dataflow form and let bindings. We believe that it is important to let the
framework developer choose the representation they are familiar with.
This does, however, have some implications on how we write passes:</p>
<ul class="simple">
<li><p>If you come from a dataflow background and want to handle lets, keep a map of var to the expressions so you can perform lookup when encountering a var. This likely means a minimum change as we already need a map from expressions to transformed expressions anyway. Note that this will effectively remove all the lets in the program.</p></li>
<li><p>If you come from a PL background and like A-normal form, we will provide a dataflow to A-normal form pass.</p></li>
<li><p>For PL folks, when you are implementing something (like a dataflow-to-ANF transformation), be mindful that expressions can be DAGs, and this usually means that we should visit expressions with a <code class="docutils literal notranslate"><span class="pre">Map&lt;Expr,</span> <span class="pre">Result&gt;</span></code> and only compute the transformed result once, so the resulting expression keeps the common structure.</p></li>
</ul>
<p>There are additional advanced concepts such as symbolic shape inference, polymorphic functions
that are not covered by this material; you are more than welcome to look at other materials.</p>
</div>
</div>


           </div>
           
          </div>
          

<footer>

    <div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
      
        <a href="relay_op_strategy.html" class="btn btn-neutral float-right" title="Relay Operator Strategy" accesskey="n" rel="next">下一个 <span class="fa fa-arrow-circle-right"></span></a>
      
      
        <a href="hybrid_script.html" class="btn btn-neutral float-left" title="混合前端开发指南" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left"></span> 上一个</a>
      
    </div>

<div id="button" class="backtop"><img src="../_static//img/right.svg" alt="backtop"/> </div>
<section class="footerSec">
    <div class="footerHeader">
      <ul class="d-flex align-md-items-center justify-content-between flex-column flex-md-row">
        <li class="copywrite d-flex align-items-center">
          <h5 id="copy-right-info">© 2020 Apache Software Foundation | All right reserved</h5>
        </li>
      </ul>

    </div>

    <ul>
      <li class="footernote">Copyright © 2020 The Apache Software Foundation. Apache TVM, Apache, the Apache feather, and the Apache TVM project logo are either trademarks or registered trademarks of the Apache Software Foundation.</li>
    </ul>

</section>
</footer>
        </div>
      </div>

    </section>

  </div>
  

    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>

  </body>
  <script type="text/javascript">
      jQuery(function () {
          SphinxRtdTheme.Navigation.enable(true);
      });
  </script>

  
  
    
    <!-- Theme Analytics -->
    <script>
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

    ga('create', 'UA-75982049-2', 'auto');
    ga('send', 'pageview');
    </script>

    
   

</body>
</html>